package com.example.javamaday.reentrantlock;

import java.util.concurrent.locks.ReentrantLock;

/**
 * ReentrantLock学习（四）：公平锁
 * 那如何能保证每个线程都能拿到锁呢，队列FIFO是一个完美的解决方案，也就是先进先出，java的
 * ReenTrantLock也就是用队列实现的公平锁和非公平锁。
 * <p>
 * 在公平的锁中，如果有另一个线程持有锁或者有其他线程在等待队列中等待这个所，那么新发出的请求的线程
 * 将被放入到队列中。而非公平锁上，只有当锁被某个线程持有时，新发出请求的线程才会被放入队列中
 * （此时和公平锁是一样的）。所以，它们的差别在于非公平锁会有更多的机会去抢占锁。
 *
 * 优缺点：
 * 非公平锁性能高于公平锁性能。首先，在恢复一个被挂起的线程与该线程真正运行之间存在着严重的延迟。
 * 而且，非公平锁能更充分的利用cpu的时间片，尽量的减少cpu空闲的状态时间。
 *
 * 使用场景：
 * 使用场景的话呢，其实还是和他们的属性一一相关，举个栗子：如果业务中线程占用(处理)时间要远长于
 * 线程等待，那用非公平锁其实效率并不明显，但是用公平锁会给业务增强很多的可控制性。
 *
 */
public class ReentrantLock4 {

    //private static ReentrantLock lock = new ReentrantLock(false);
    private static ReentrantLock lock = new ReentrantLock(true);

    public static void main(String[] args) {
        testFairLock();
    }

    private static void testFairLock() {
        Runnable runnable = ReentrantLock4::testLock;
        Thread[] threadArray = new Thread[3];
        for (int i = 0; i < 3; i++) {
            threadArray[i] = new Thread(runnable);
        }
        for (int i = 0; i < 3; i++) {
            threadArray[i].start();
        }
    }

    private static void testLock() {
        for (int i = 0; i < 10; i++) {
            try {
                lock.lock();
                System.out.println(Thread.currentThread().getName() + "获得了锁");
            } finally {
                lock.unlock();
            }
        }
    }
}
